package com.opengw.configuration.route;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import com.opengw.configuration.config.RouteConfig;
import com.opengw.configuration.entity.Content;
import com.opengw.exception.OpenGWException;

@Entity
@Table(name = "route")
public class Route implements Serializable{
	
	private static final long serialVersionUID = -1184692040215725141L;
	
	private long routeId;
	private String requestPath;
	private String routeURL;
	private String availableMethods;
	private int connectTimeOut;
	private int readTimeOut;
	private boolean configBeforeRequest;
	private boolean configAfterResponse;
	private List<RouteConfig> routeConfigList;
	private Content defaultContent;
	
	public Route(){
		this.routeConfigList = new ArrayList<RouteConfig>();
	}
	
	public Route(String availableMethods){
		this.routeConfigList = new ArrayList<RouteConfig>();
		this.availableMethods = availableMethods;
	}
	
	public void setRouteId(long routeId) {
		this.routeId = routeId;
	}
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "route_id")
	public long getRouteId() {
		return routeId;
	}
	public void setRequestPath(String requestPath) {
		this.requestPath = requestPath;
	}
	@Column(name = "request_path", unique = true)
	public String getRequestPath() {
		return requestPath;
	}
	public void setAvailableMethods(String availableMethods) {
		this.availableMethods = availableMethods;
	}
	@Column(name = "available_mathods")
	public String getAvailableMethods() {
		return availableMethods;
	}
	public void setRouteConfigList(List<RouteConfig> routeConfigList) {
		this.routeConfigList = routeConfigList;
		for(RouteConfig config : this.routeConfigList){
			if(config.isChangeRequest() || config.isControlRequest())
				this.configBeforeRequest = true;
			if(config.isChangeResponse() || config.isControlResponse())
				this.configAfterResponse = true;
		}
	}
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@JoinColumn(name="route_ref")
	public List<RouteConfig> getRouteConfigList() {
		return routeConfigList;
	}
	public void addRouteConfig(RouteConfig config){
		if(config.isChangeRequest() || config.isControlRequest())
			this.configBeforeRequest = true;
		if(config.isChangeResponse() || config.isControlResponse())
			this.configAfterResponse = true;
		
		this.routeConfigList.add(config);
	}
	public void removeRouteConfig(long configId) throws OpenGWException{
		boolean removed = false;
		for(RouteConfig config : this.routeConfigList){
			if(config.getConfigId() == configId){
				removed = true;
				break;
			}
		}
		if(!removed)
			throw new OpenGWException(OpenGWException.ROUTE_CONFIG_NOT_FOUND);
		
		for(RouteConfig config : this.routeConfigList){
			if(config.isChangeRequest() || config.isControlRequest())
				this.configBeforeRequest = true;
			if(config.isChangeResponse() || config.isControlResponse())
				this.configAfterResponse = true;
		}
		
	}
	@Transient
	public boolean isConfigBeforeRequest() {
		return configBeforeRequest;
	}
	@Transient
	public boolean isConfigAfterResponse() {
		return configAfterResponse;
	}
	public void setRouteURL(String routeURL) {
		this.routeURL = routeURL;
	}
	@Column(name = "route_url")
	public String getRouteURL() {
		return routeURL;
	}
	public void setDefaultContent(Content defaultContent) {
		this.defaultContent = defaultContent;
	}
	
	@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@JoinColumn(name="content_ref")
	public Content getDefaultContent() {
		return defaultContent;
	}

	public void setConnectTimeOut(int connectTimeOut) {
		this.connectTimeOut = connectTimeOut;
	}

	@Column(name = "connection_time_out")
	public int getConnectTimeOut() {
		return connectTimeOut;
	}

	public void setReadTimeOut(int readTimeOut) {
		this.readTimeOut = readTimeOut;
	}

	@Column(name = "read_time_out")
	public int getReadTimeOut() {
		return readTimeOut;
	}

}
